package gupao.concurrency.lock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;

public class TwinsLock {

    static class Sync extends AbstractQueuedSynchronizer{
        Sync(int count) {
            if(count <= 0){
                throw new IllegalArgumentException("state must > 0");
            }
            setState(count);
        }
        @Override
        protected int tryAcquireShared(int reduceCount) {
            for(;;){
                int currentState = getState();
                int newState = currentState - reduceCount;
                if(newState < 0 || compareAndSetState(currentState,newState)){
                    return newState;
                }
            }
        }
        @Override
        protected boolean tryReleaseShared(int returnCount) {
            for(;;){
                int currentState = getState();
                int newState = currentState + returnCount;
                if(compareAndSetState(currentState, newState)){
                    return true;
                }
            }
        }
    }

    private final Sync sync = new Sync(2);

    public void lock(){
        sync.acquireShared(1);
    }

    public boolean tryLock(){
        return sync.tryAcquireShared(1) >= 0;
    }

    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException{
        return sync.tryAcquireSharedNanos(1,unit.toNanos(time));
    }

    public void unlock(){
        sync.releaseShared(1);
    }
}
